﻿Public Class Form1
    Dim arrayListOfFiles As New ArrayList()
    Dim arrayLineCSV As New ArrayList()

    Dim dotFileName As String
    Dim graphName As String
    Dim svgFileName As String
    Dim consoFileName As String

    Dim csvFileHashTable As New Hashtable()
    Dim csvFileContent As New Hashtable()
    Dim hashTableAlreadyProcessed As New Hashtable
    Dim HashTableDirectPredecessors As New Hashtable()
    Dim HashTableSubJobs As New Hashtable()
    Dim HashTableAllPredecessors As New Hashtable()
    Dim HashTableJobDescription As New Hashtable()
    Dim HashTableAllSuccessors As New Hashtable()
    Dim HashTableDirectSuccessors As New Hashtable()
    Dim csvSeparator As String
    Dim dotFileContent As New ArrayList

    ' list all files in all subdirectory recurcively
    Private Sub listAllSubdirectoryInDirectory(ByVal myDir As String, ByVal init As Integer)
        If (init = 0) Then
            listAllFilesInDirectory(myDir, TextBoxFileNameExtension.Text)
            init = 1
        End If
        For Each foundDirectory As String In _
                  My.Computer.FileSystem.GetDirectories(myDir)
            listAllFilesInDirectory(foundDirectory, TextBoxFileNameExtension.Text)
            listAllSubdirectoryInDirectory(foundDirectory, init)
        Next
    End Sub

    ' list files in first level only not in subdirectory
    Private Sub listAllFilesInDirectory(ByVal myPath As String, ByVal extension As String)
        If (extension = "") Then
            extension = "*.*"
        End If
        Application.DoEvents()
        For Each foundFile As String In My.Computer.FileSystem.GetFiles(myPath, _
                            FileIO.SearchOption.SearchTopLevelOnly, _
                            extension)
            arrayListOfFiles.Add(foundFile)
        Next
        Dim counter As Integer = arrayListOfFiles.Count
        LabelProgressBar.Text = "Counting files, Please wait ... " & counter

    End Sub

    Private Sub processInputFiles()
        Dim MyXL As Object
        MyXL = Nothing
        MyXL = CreateObject("Excel.Application")
        ProgressBar.Maximum = arrayListOfFiles.Count
        ProgressBar.Value = 0

        Dim counter, all, numberOfExcelApplication As Integer
        counter = 0
        numberOfExcelApplication = 0
        all = arrayListOfFiles.Count
        LabelProgressBar.Text = "Going to process " & arrayListOfFiles.Count & " files ..."

        For Each file In arrayListOfFiles
            counter = counter + 1
            Dim newCSVfileName As String = TextBoxOutputCSVFolder.Text + "\csv\" + _
            System.IO.Path.GetFileName(file) + ".csv"

            If CheckBoxOverwriteFiles.CheckState = 1 Or Not FileExists(newCSVfileName) Then
                Dim xlBook = MyXL.Workbooks.Open(file)
                xls2csv(MyXL, file)
            End If
            pushCSVFileContentIntotable(newCSVfileName)
            ProgressBar.Value = counter
            LabelProgressBar.Text = "Processing files " & counter & "/" & all & " " & System.IO.Path.GetFileName(newCSVfileName)
            Application.DoEvents()
        Next
        MyXL.Quit()
    End Sub

    Function FileExists(ByVal sFileName As String) As Boolean
        On Error Resume Next
        FileExists = ((GetAttr(sFileName) And vbDirectory) = 0)
    End Function

    Function generateSVGFile() As Boolean
        If CheckBoxCreateSVGFile.CheckState = 0 Then
            Return False
        End If

        On Error Resume Next
        Kill(svgFileName)
        On Error GoTo 0
        LabelProgressBar.Text = "Last step : creating file " & svgFileName & " please wait ...."
        Application.DoEvents()

        Dim l_cmd As String
        l_cmd = "dot -Tsvg " + """" + dotFileName + """" + " -o " + """" + svgFileName + """"
        Shell(Environ$("COMSPEC") + " /c " + l_cmd$)
        Return True
    End Function

    Function openSVGFile() As Boolean
        Shell(Environ$("COMSPEC") + " /c " + svgFileName$)
        Return True
    End Function

    Private Sub listAllFilesInDirectoryAndSubDirectory(ByVal myPath As String, ByVal extension As String)
        If (extension = "") Then
            extension = "*.*"
        End If

        arrayListOfFiles.Clear()

        For Each foundFile As String In My.Computer.FileSystem.GetFiles(myPath, _
                            FileIO.SearchOption.SearchAllSubDirectories, _
                            extension)
            'Debug.Print(foundFile)
            'Excel2CSV(foundFile)
            arrayListOfFiles.Add(foundFile)
        Next
    End Sub

    Private Function intersection(ByRef l1 As ArrayList, ByRef l2 As ArrayList) As ArrayList
        Dim l_array As New ArrayList
        For Each i In l1
            If l2.Contains(i) Then
                l_array.Add(i)
            End If
        Next
        Return l_array
    End Function
    Private Function union(ByRef l1 As ArrayList, ByRef l2 As ArrayList) As ArrayList
        Dim l_array As New ArrayList

        Return l_array
    End Function

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ProgressBar.Maximum = 100
        ProgressBar.Value = 0
        csvSeparator = ";"

        TabControl1.TabPages.Item(1).Enabled = False
        TabControl1.TabPages.Item(2).Enabled = False

        TextBoxPathFolderIn.Text = GetSetting("jobsets2csv", "Settings", "TextBoxPathFolderIn", TextBoxPathFolderIn.Text)
        TextBoxFilterFilenameNotContain.Text = GetSetting("jobsets2csv", "Settings", "TextBoxFilterFilenameNotContain", TextBoxFilterFilenameNotContain.Text)
        TextBoxOutputCSVFolder.Text = GetSetting("jobsets2csv", "Settings", "TextBoxOutputCSVFolder", TextBoxOutputCSVFolder.Text)
        TextBoxFileNameExtension.Text = GetSetting("jobsets2csv", "Settings", "TextBoxFileNameExtension", TextBoxFileNameExtension.Text)
        CheckBoxOverwriteFiles.CheckState = GetSetting("jobsets2csv", "Settings", "CheckBoxOverwriteFiles", CheckBoxOverwriteFiles.CheckState)
        CheckBoxIgnoreSubJobs.CheckState = GetSetting("jobsets2csv", "Settings", "CheckBoxIgnoreSubjobs", CheckBoxIgnoreSubJobs.CheckState)
        CheckBoxCreateSVGFile.CheckState = GetSetting("jobsets2csv", "Settings", "CheckBoxCreateSVGFile", CheckBoxCreateSVGFile.CheckState)
        CheckBoxConsoFile.CheckState = GetSetting("jobsets2csv", "Settings", "CheckBoxConsoFile", CheckBoxConsoFile.CheckState)
        CheckBoxDotFile.CheckState = GetSetting("jobsets2csv", "Settings", "CheckBoxDotFile", CheckBoxDotFile.CheckState)

        changeButtonOKStatus()
    End Sub

    Private Sub changeButtonOKStatus()
        If Len(TextBoxPathFolderIn.Text) = 0 Or Len(TextBoxOutputCSVFolder.Text) = 0 Then
            ButtonOK.Enabled = False
        ElseIf Len(TextBoxPathFolderIn.Text) > 0 And Len(TextBoxOutputCSVFolder.Text) > 0 Then
            ButtonOK.Enabled = True
        End If
    End Sub


    Private Function InitializeOutputFile() As Boolean
        ComboBoxListPredecessor.Items.Clear()
        ComboBox1.Items.Clear()
        ComboBox2.Items.Clear()
        dotFileContent.Clear()
        arrayListOfFiles.Clear()
        arrayLineCSV.Clear()
        dotFileName = Nothing
        svgFileName = Nothing
        consoFileName = Nothing
        csvFileHashTable.Clear()
        csvFileContent.Clear()
        HashTableDirectPredecessors.Clear()
        HashTableAllPredecessors.Clear()
        HashTableJobDescription.Clear()
        HashTableAllSuccessors.Clear()
        HashTableDirectSuccessors.Clear()

        Dim l_prefix As String
        l_prefix = Replace(TextBoxFileNameExtension.Text, "*", "")
        graphName = Replace(TextBoxFileNameExtension.Text, "*", "")
        graphName = Replace(graphName, ".", "")
        graphName = "graph_" & graphName

        l_prefix = TextBoxOutputCSVFolder.Text + "\tracking-" + l_prefix

        svgFileName = l_prefix + ".svg"
        dotFileName = l_prefix + ".dot"
        consoFileName = l_prefix + "_consolidated.csv"
        TextBoxConsoFile.Text = consoFileName
        TextBoxDotFile.Text = dotFileName
        TextBoxSVGFile.Text = svgFileName
        TextBoxConsoFile.Enabled = False
        TextBoxDotFile.Enabled = False
        TextBoxSVGFile.Enabled = False

        On Error Resume Next
        My.Computer.FileSystem.CreateDirectory(TextBoxOutputCSVFolder.Text)
        My.Computer.FileSystem.CreateDirectory(TextBoxOutputCSVFolder.Text & "\dot\")
        My.Computer.FileSystem.CreateDirectory(TextBoxOutputCSVFolder.Text & "\csv\")
        On Error GoTo 0

        l_prefix = Replace(TextBoxFileNameExtension.Text, "*", "")
        l_prefix = Replace(l_prefix, ".xls", "")
        l_prefix = Replace(l_prefix, ".", "_")

    End Function

    Private Sub ButtonOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonOK.Click

        InitializeOutputFile()

        LabelProgressBar.Text = ""
        LabelProgressBar.Text = "Counting files, Please wait ..."
        csvFileHashTable.Clear()
        ProgressBar.Value = 0
        ProgressBar.Maximum = 0

        arrayListOfFiles.Clear()

        SaveSetting("jobsets2csv", "Settings", "TextBoxPathFolderIn", TextBoxPathFolderIn.Text)
        SaveSetting("jobsets2csv", "Settings", "TextBoxFilterFilenameNotContain", TextBoxFilterFilenameNotContain.Text)
        SaveSetting("jobsets2csv", "Settings", "TextBoxOutputCSVFolder", TextBoxOutputCSVFolder.Text)
        SaveSetting("jobsets2csv", "Settings", "TextBoxFileNameExtension", TextBoxFileNameExtension.Text)
        SaveSetting("jobsets2csv", "Settings", "CheckBoxOverwriteFiles", CheckBoxOverwriteFiles.CheckState)
        SaveSetting("jobsets2csv", "Settings", "CheckBoxIgnoreSubjobs", CheckBoxIgnoreSubJobs.CheckState)
        SaveSetting("jobsets2csv", "Settings", "CheckBoxCreateSVGFile", CheckBoxCreateSVGFile.CheckState)
        SaveSetting("jobsets2csv", "Settings", "CheckBoxConsoFile", CheckBoxConsoFile.CheckState)
        SaveSetting("jobsets2csv", "Settings", "CheckBoxDotFile", CheckBoxDotFile.CheckState)

        ' We get the same result with the 2 functions bellow
        ' It's better to use the 2nd which use windows native API
        LabelProgressBar.Text = "Counting number of files ... Please wait"
        Application.DoEvents()
        listAllSubdirectoryInDirectory(TextBoxPathFolderIn.Text, 0)
        'listAllFilesInDirectoryAndSubDirectory(TextBoxPathFolderIn.Text, _
        '                                       TextBoxFileNameExtension.Text)
        processInputFiles()

        If createDotFile() = True Then
            If generateSVGFile() = True Then
                openSVGFile()
            End If

        End If
        Application.DoEvents()
        TabControl1.TabPages.Item(1).Enabled = True
        TabControl1.TabPages.Item(2).Enabled = True
        LabelProgressBar.Text = "Scan Completed."
        Application.DoEvents()

    End Sub


    Private Function createDotFile() As Boolean
        If CheckBoxDotFile.CheckState = 0 Then
            Return False
        End If

        On Error Resume Next
        Kill(dotFileName)
        On Error GoTo 0

        LabelProgressBar.Text = "Last step : creating file " & dotFileName & " please wait ...."
        ' FIX ME USE HERE THE DOT TEMPLATE !!!
        My.Computer.FileSystem.WriteAllText(dotFileName, "digraph " + graphName + " {" + vbNewLine, True)
        Application.DoEvents()
        For Each Key In HashTableDirectPredecessors.Keys
            For Each value In HashTableDirectPredecessors(Key)
                addEntryToDotFileContent(Key, value)
            Next
        Next
        Application.DoEvents()
        My.Computer.FileSystem.WriteAllText(dotFileName, "}" + vbNewLine, True)

        Return True
    End Function

    Private Sub TextBoxOutputCSVFolder_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBoxOutputCSVFolder.TextChanged
        changeButtonOKStatus()
    End Sub

    Private Sub ButtonCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonCancel.Click
        Application.Exit()
    End Sub

    Private Sub ButtonBrownseCSVFile_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonBrownseCSVFile.Click
        ' First create a FolderBrowserDialog object
        Dim FolderBrowserDialog1 As New FolderBrowserDialog
        Dim initPath As String

        If TextBoxPathFolderIn.Text = "" Then
            initPath = "C:\"
        Else
            initPath = TextBoxOutputCSVFolder.Text
        End If

        ' Then use the following code to create the Dialog window
        ' Change the .SelectedPath property to the default location
        With FolderBrowserDialog1
            ' Desktop is the root folder in the dialog.
            .RootFolder = Environment.SpecialFolder.Desktop
            ' Select the C:\Windows directory on entry.
            .SelectedPath = initPath
            ' Prompt the user with a custom message.
            .Description = "Select the source directory"
            If .ShowDialog = DialogResult.OK Then
                ' Display the selected folder if the user clicked on the OK button.
                TextBoxOutputCSVFolder.Text = .SelectedPath
                SaveSetting("jobsets2csv", "Settings", "TextBoxOutputCSVFolder", TextBoxOutputCSVFolder.Text)
            End If
        End With
    End Sub

    ' FIX ME USE HERE THE DOT TEMPLATE !!!
    Function addEntryToDotFileContent(ByVal succ As String, ByVal pred As String) As Boolean
        '        Dim l_str As String = """" + pred + " \n " + HashTableJobDescription(pred) + """->""" + succ + """"
        Dim l_str As String = """" + pred + """->""" + succ + """"

        If pred.Contains("$$") Then
            l_str = l_str + " [style=dotted,color=blue];"
        Else
            l_str = l_str + " [shape=box,color=black];"
        End If
        dotFileContent.Add(l_str)
        My.Computer.FileSystem.WriteAllText(dotFileName, l_str + vbNewLine, True)
        Return True
    End Function

    Private Sub xls2csv(ByVal MyXL As Object, ByVal filename As String)
        Dim basename As String
        basename = System.IO.Path.GetFileName(filename)
        Dim n, k As Integer
        n = 1
        k = 4
        Dim newCSVfileName As String = TextBoxOutputCSVFolder.Text + "\csv\" + _
    System.IO.Path.GetFileName(filename) + ".csv"

        On Error Resume Next
        My.Computer.FileSystem.DeleteFile(newCSVfileName)
        On Error GoTo 0

        Dim v1, v2 As String
        v1 = MyXL.Worksheets(1).Cells(k, 1).Value() 'JOBSET_NAME
        v2 = MyXL.Worksheets(1).Cells(k, 2).Value() 'JOB_NAME

        While (Not (v1 = Nothing And v2 = Nothing))

            Dim lineArray As New ArrayList
            Dim l_tmp As String
            Application.DoEvents()

            For i = 1 To 71 Step 1
                l_tmp = MyXL.Worksheets(1).Cells(k, i).value()
                lineArray.Add(l_tmp)
            Next i
            Dim csvLine As String
            csvLine = Join(lineArray.ToArray, csvSeparator)

            If (k = 4) Then
                csvLine = Replace(csvLine, Chr(10), " ")
            End If

            My.Computer.FileSystem.WriteAllText(newCSVfileName, csvLine + vbNewLine, True)

            If CheckBoxConsoFile.CheckState = 1 Then
                My.Computer.FileSystem.WriteAllText(consoFileName, csvLine + vbNewLine, True)
            End If

            k = k + 1
            v1 = MyXL.Worksheets(1).Cells(k, 1).Value()
            v2 = MyXL.Worksheets(1).Cells(k, 2).Value()
        End While
        MyXL.Quit()
        MyXL = Nothing
    End Sub

    Private Sub pushCSVFileContentIntotable(ByVal filename As String)
        Dim basename As String
        basename = System.IO.Path.GetFileName(filename)
        Dim fileReader As String
        fileReader = My.Computer.FileSystem.ReadAllText(filename)
        Dim strOneLineOfCSVFile() As String = Split(fileReader, vbNewLine)

        On Error Resume Next
        If csvFileContent.ContainsKey(basename) Then
            csvFileContent(basename).Clear()
        End If
        csvFileContent.Add(basename, New ArrayList())
        On Error GoTo 0

        Dim compt As Integer = 0
        For Each l_str In strOneLineOfCSVFile
            If Not compt = 0 Then 'Skip the first line header
                Dim oneLine() As String = Split(l_str, ";")
                Application.DoEvents()
                csvFileContent(basename).add(oneLine)

                If (oneLine.Count > 26) Then
                    Dim l_jobsetname As String = oneLine(0)
                    Dim l_jobname As String = oneLine(1)
                    Dim l_description As String = oneLine(2)
                    Dim l_jobsetpred As String = oneLine(3)
                    Dim l_jobpred As String = oneLine(4)
                    Dim l_prior As String = oneLine(5)
                    Dim l_ressource_name As String = oneLine(6)
                    Dim l_early_start As String = oneLine(26)
                    If (compt = 1) Then
                        HashTableJobDescription(l_jobsetname) = l_description
                    End If

                    If Not (l_jobsetname = Nothing And l_jobname = Nothing) Then
                        If Not l_jobsetname = Nothing Then
                            addToHash(HashTableDirectPredecessors, l_jobsetname, l_jobsetpred, 0, l_prior)
                            addToHash(HashTableDirectSuccessors, l_jobsetname, l_jobsetpred, 1, l_prior)
                        ElseIf Not l_jobname = Nothing Then
                            If CheckBoxIgnoreSubJobs.CheckState = 0 Then
                                If l_jobpred = Nothing Then

                                    Dim value As String = Microsoft.VisualBasic.Left(l_jobname, 16)
                                    addToHash(HashTableDirectPredecessors, l_jobname, value, 0, l_prior)
                                    addToHash(HashTableDirectSuccessors, l_jobname, value, 1, l_prior)
                                    HashTableSubJobs(l_jobname) = value

                                Else
                                    addToHash(HashTableDirectPredecessors, l_jobname, l_jobpred, 0, l_prior)
                                    addToHash(HashTableDirectSuccessors, l_jobname, l_jobpred, 1, l_prior)
                                End If
                            End If
                        End If
                    End If
                End If
            End If
            compt = compt + 1
        Next
    End Sub

    Private Function addToHash(ByRef hash As Hashtable, ByVal key As String, ByVal value As String, ByVal i As Integer, ByVal l_prior As String) As Boolean
        If Not l_prior = "" Then
            Return False
        End If

        ComboBox1.Items.Add(key)
        ComboBox2.Items.Add(key)
        ComboBoxListPredecessor.Items.Add(key)
        ComboBox1.Items.Add(value)
        ComboBox2.Items.Add(value)
        ComboBoxListPredecessor.Items.Add(value)

        If i = 0 Then
            If Not hash.ContainsKey(key) Then
                hash.Add(key, New ArrayList())
            End If
            hash(key).add(value)
        Else
            If Not hash.ContainsKey(value) Then
                hash.Add(value, New ArrayList())
            End If
            hash(value).add(key)
        End If
        Return True
    End Function

    Private Sub ButtonBrownseFolder_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonBrownseFolder.Click

        ' First create a FolderBrowserDialog object
        Dim FolderBrowserDialog1 As New FolderBrowserDialog

        Dim initPath As String
        If TextBoxPathFolderIn.Text = "" Then
            initPath = "C:\"
        Else
            initPath = TextBoxPathFolderIn.Text
        End If

        ' Then use the following code to create the Dialog window
        ' Change the .SelectedPath property to the default location
        With FolderBrowserDialog1
            ' Desktop is the root folder in the dialog.
            .RootFolder = Environment.SpecialFolder.Desktop
            ' Select the C:\Windows directory on entry.
            .SelectedPath = initPath
            ' Prompt the user with a custom message.
            .Description = "Select the source directory"
            If .ShowDialog = DialogResult.OK Then
                ' Display the selected folder if the user clicked on the OK button.
                TextBoxPathFolderIn.Text = .SelectedPath
                SaveSetting("jobsets2csv", "Settings", "TextBoxPathFolderIn", TextBoxPathFolderIn.Text)
            End If
        End With
    End Sub

    Private Sub ButtonDisplayJobsBetween_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonDisplayJobsBetween.Click
        Dim s1 As String = ComboBox1.Text
        Dim s2 As String = ComboBox2.Text
        succ(s1, s1, 0)
        pred(s2, s2, 0)
        Dim l_array As New ArrayList
        l_array = intersection(HashTableAllSuccessors(s1), HashTableAllPredecessors(s2))
        RichTextBox1.Text = Join(l_array.ToArray, vbNewLine)

    End Sub


    Private Sub pred(ByVal job1 As String, ByVal job2 As String, ByVal i As Integer)
        If i = 0 Then
            hashTableAlreadyProcessed.Clear()
            If HashTableAllPredecessors.ContainsKey(job2) Then
                HashTableAllPredecessors(job2).Clear()
            Else
                HashTableAllPredecessors.Add(job2, New ArrayList())
            End If
        End If

        If hashTableAlreadyProcessed.ContainsKey(job1) Then
            Exit Sub
        End If

        HashTableAllPredecessors(job2).add(job1)
        hashTableAlreadyProcessed(job1) = 1
        i = i + 1

        If HashTableDirectPredecessors.ContainsKey(job1) Then
            For Each l In HashTableDirectPredecessors(job1)
                pred(l, job2, i)
            Next
        End If
    End Sub


    Private Sub succ(ByVal job1 As String, ByVal job2 As String, ByVal i As Integer)
        If i = 0 Then
            hashTableAlreadyProcessed.Clear()
            If HashTableAllSuccessors.ContainsKey(job2) Then
                HashTableAllSuccessors(job2).Clear()
            Else
                HashTableAllSuccessors.Add(job2, New ArrayList())
            End If
        End If

        If hashTableAlreadyProcessed.ContainsKey(job1) Then
            Exit Sub
        End If

        HashTableAllSuccessors(job2).add(job1)
        hashTableAlreadyProcessed(job1) = 1
        i = i + 1

        If HashTableDirectSuccessors.ContainsKey(job1) Then
            For Each l In HashTableDirectSuccessors(job1)
                succ(l, job2, i)
            Next
        End If
    End Sub

    Private Sub ButtonGoSuccPred_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonGoSuccPred.Click

        RichTextBoxPredecessor.Clear()
        RichTextBoxSuccessor.Clear()
        Dim l_select As String = ComboBoxListPredecessor.Text


        succ(l_select, l_select, 0)
        RichTextBoxSuccessor.Text = Join(HashTableAllSuccessors(l_select).toArray, vbNewLine)
        Application.DoEvents()
        pred(l_select, l_select, 0)
        RichTextBoxPredecessor.Text = Join(HashTableAllPredecessors(l_select).toArray, vbNewLine)
        Application.DoEvents()
    End Sub

    Private Sub ButtonRestoreDotTemplate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonRestoreDotTemplate.Click

    End Sub

    Private Sub ButtonSaveDotTemplate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSaveDotTemplate.Click

    End Sub
End Class
